import csv
import datetime
import os

from pyecharts import options as opts
from pyecharts.charts import Bar, Page

from monit.process_monitor import ProcessMonitorInfo

# dict_keys(['cpu%/s', '已用内存/%', '磁盘读取MB/s', '磁盘写入MB/s', '网络上传MB/s',
#               '网络下载MB/s'])
# 获取当前文件的绝对路径
current_file_path = os.path.abspath(__file__)
current_file_path = os.path.dirname(current_file_path)


def csv_to_dict(filename):
    with open(filename, 'r', encoding='utf-8') as file:
        reader = csv.DictReader(file)
        csv_data_dict = {}
        for row in reader:
            for key, value in row.items():
                if key not in csv_data_dict:
                    csv_data_dict[key] = []
                csv_data_dict[key].append(value)
    return csv_data_dict


def add_seconds_to_time(time_string, seconds):
    # 将时间字符串转换为datetime对象
    time_obj = datetime.datetime.strptime(time_string, "%H:%M:%S")

    # 将秒数转换为timedelta对象
    delta = datetime.timedelta(seconds=seconds)

    # 相加得到新的时间对象
    new_time_obj = time_obj + delta

    # 格式化为字符串，并返回结果
    return new_time_obj.strftime("%H:%M:%S")


class SystemInfo:
    def __init__(self, max_memory):
        self.max_memory = str(max_memory)


def generate_chart_list(time_str, title_list, data_dict):
    """

    :param time_str: 2023/6/29 15:05:11 - 2023/6/29 15:10:05
    :param title_list: ["cpu %/s", "used mem %", "disk read MB/s", "disk write MB/s",
     "net upload MB/s","net download MB/s"]
    :param data_dict: 源数据csv转dict
    :return:
    """
    time_value = data_dict.get('time')  # 获取时间值列表，例如：['18:01:20']
    # 初始化 indices 以包含所有可能的索引
    indices = list(range(len(time_value)))

    if time_str is not None:
        # 获取开始时间和结束时间
        start_time_str, end_time_str = time_str.split('-')  # 提取开始时间和结束时间

        # 将字符串转换为时间对象
        start_time = datetime.datetime.strptime(start_time_str, "%H:%M:%S").time()
        end_time = datetime.datetime.strptime(end_time_str, "%H:%M:%S").time()

        # 筛选符合时间范围的索引
        indices = [i for i, t in enumerate(time_value) if
                   start_time <= datetime.datetime.strptime(t, "%H:%M:%S").time() <= end_time]

        # 筛选与时间值对应的时间值
        time_value = [t for i, t in enumerate(time_value) if i in indices]

    chart_list = []

    for i, title in enumerate(title_list):
        # 筛选与时间值对应的Y轴值
        y_value = data_dict.get(title)

        #  筛选与时间值对应的Y轴值
        y_value = [y for j, y in enumerate(y_value) if j in indices]

        max_y = 100 if '%' in title else None

        chart_obj = (
            Bar(init_opts=opts.InitOpts(width="50%", height="300px", bg_color='white'))  # 创建柱状图对象
            .add_xaxis(time_value)  # 设置X轴数据
            .add_yaxis(title, y_value)  # 设置Y轴数据和名称
            .set_series_opts(label_opts=opts.LabelOpts(is_show=False))  # 隐藏数据标签
            # .set_series_opts(label_opts=opts.LabelOpts(is_show=True, position="top"))  # 显示数据标签，位置设置为顶部
            .set_global_opts(
                title_opts=opts.TitleOpts(title=title),  # 设置图表标题
                datazoom_opts=opts.DataZoomOpts(range_start=0, range_end=100),  # 设置数据缩放范围
                toolbox_opts=opts.ToolboxOpts(),  # 设置工具箱，包含导出图片等功能
                # 设置 Y 轴最大值，如果是 'cpu百分比/s' 则设置为100
                yaxis_opts=opts.AxisOpts(max_=max_y)
            )
        )
        chart_obj.chart_id = f"{i + 1}"  # 设置图表的唯一ID
        chart_list.append(chart_obj)  # 将图表对象添加到列表中

    return chart_list  # 返回图表对象列表


def generate_resize_html(chart_list, dest="target.html", template=os.path.join(current_file_path, 'temp.html'),
                         web_title=None):
    """

    :param web_title: 网页的title
    :param chart_list：包含柱状图对象的列表。
    :param dest：生成的 HTML 文件的目标路径，默认为 "target.html"。
    :param template：HTML 模板文件的路径，默认为 "temp.html"。
    :return:
    """

    # 将所有柱状图对象添加到 page 中;DraggablePageLayout 表示可拖拽的页面布局
    if web_title:
        page = Page(layout=Page.DraggablePageLayout, page_title=web_title)
    else:
        page = Page(layout=Page.DraggablePageLayout)
    for chart in chart_list:
        page.add(chart)

    # 将 page 渲染为 HTML 文件
    page.render(template)

    # 调用 Page.save_resize_html 方法生成可调整布局的 HTML 文件
    Page.save_resize_html(template, cfg_file=os.path.join(current_file_path, 'chart_config.json'), dest=dest)


def open_chart_html(monit_file_path, start_time=None, duration=None, file_title_list=None):
    """


    :param monit_file_path:  监控信息,2023-07-20_SystemMonitorInfo_sql.csv
    :param start_time: 17:10
    :param duration: 持续时间/分钟
    :param file_title_list: 图表的标题,['cpu%/s', '已用内存/%', '磁盘读取MB/s', '磁盘写入MB/s', '网络上传MB/s', '网络下载MB/s']
    :return:
    """
    file_data_dict = csv_to_dict(monit_file_path)
    if "io_input MB/s" in file_data_dict.keys():
        file_title_list = ProcessMonitorInfo.header[2:]

    if start_time is None:
        # 不筛选时间,全部生成
        result_chart_list = generate_chart_list(None, file_title_list, file_data_dict)
    else:
        start_time = f'{start_time}:00'
        time_scale = f'{start_time}-{add_seconds_to_time(start_time, 60 * int(duration))}'
        result_chart_list = generate_chart_list(time_scale, file_title_list, file_data_dict)

    # 使用os.path.basename获取文件名
    file_name = os.path.basename(monit_file_path)
    file_name = os.path.splitext(file_name)[0]
    # 获取当前工作目录
    current_dir = os.getcwd()
    # 将目录和文件名组合成一个完整的路径
    html_dir = os.path.join(current_dir, 'html_output')
    if not os.path.exists(html_dir):
        os.makedirs(html_dir)
    html_path = os.path.join(html_dir, f'{file_name}.html')
    generate_resize_html(result_chart_list, html_path, web_title=file_name)
    # open
    if os.name == 'nt':
        os.system(html_path)

# open_chart_html()
